package com.xiaoxx.service.impl;

import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationOutput;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.aigc.generation.models.QwenParam;
import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesis;
import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesisParam;
import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesisResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoxx.common.error.ErrorException;
import com.xiaoxx.config.QwenAuthConfig;
import com.xiaoxx.config.ThreadUtils;
import com.xiaoxx.enums.CreativeWordNums;
import com.xiaoxx.enums.ResdisKeyEnum;
import com.xiaoxx.mapper.ChatContentMapper;
import com.xiaoxx.model.dto.chat.ChatDto;
import com.xiaoxx.model.entity.chat.ChatContent;
import com.xiaoxx.model.entity.chat.ChatMenu;
import com.xiaoxx.model.entity.chat.ChatModel;
import com.xiaoxx.model.entity.sys.SysRole;
import com.xiaoxx.model.vo.chat.ChatContentCacheVo;
import com.xiaoxx.model.vo.chat.ChatContentListVo;
import com.xiaoxx.model.vo.chat.ChatTokenStatisticsAllVo;
import com.xiaoxx.model.vo.chat.ChatTokenStatisticsVo;
import com.xiaoxx.rabbitmq.IRabbitMQMessageClient;
import com.xiaoxx.rabbitmq.bean.MyMessage;
import com.xiaoxx.rabbitmq.constant.MessageType;
import com.xiaoxx.rabbitmq.constant.RabbitQueueExchangeConstant;
import com.xiaoxx.server.SseEmitterServer;
import com.xiaoxx.service.ChatContentService;
import com.xiaoxx.service.ChatMenuService;
import com.xiaoxx.service.ChatModelService;
import com.xiaoxx.service.SysRoleService;
import com.xiaoxx.utils.BeanDtoVoUtil;
import com.xiaoxx.utils.JwtUtil;
import com.xiaoxx.utils.OssUtil;
import com.xiaoxx.utils.date.LocalDateTimeUtil;
import io.reactivex.Flowable;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author HX
 * @since 2023-07-19
 */
@Service
@Slf4j
public class ChatContentServiceImpl extends ServiceImpl<ChatContentMapper, ChatContent> implements ChatContentService {
    @Autowired
    private QwenAuthConfig qwenAuthConfig;

    private Map<String, SseEmitterServer> clients = new HashMap<>();

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private ChatMenuService chatMenuService;

    @Autowired
    private SysRoleService roleService;

    @Autowired
    private ChatModelService chatModelService;

    @Autowired
    private OssUtil ossUtil;

    public final static List<String> userCode = new ArrayList<>();

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private IRabbitMQMessageClient rabbitMQMessageClient;


    public ChatContentServiceImpl() {
        // 获取不到用户信息的
        userCode.add("USER");
        userCode.add("Test");
    }

    /**
     * 开始聊天
     *
     * @param chatVo
     * @throws NoApiKeyException
     * @throws InputRequiredException
     * @throws IOException
     */
    @Override
    public void start(ChatDto chatVo) {
        log.info("chat 开始 聊天消息 {}", chatVo.getQuestion());
        chatVo.setUserId(JwtUtil.getJwtUser(request).getUserId());
        MyMessage<ChatDto> message = new MyMessage<>(IdWorker.getIdStr(),
                RabbitQueueExchangeConstant.ExchangeName.ALI_CHAT_EXCHANGE,
                RabbitQueueExchangeConstant.RoutingKey.ALI_CHAT_ROUTINGKEY,
                chatVo,
                MessageType.RELIANT);
        rabbitMQMessageClient.send(message);
    }


    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = RabbitQueueExchangeConstant.QueueName.ALI_CHAT_QUEUE, durable = "true", autoDelete = "false"),
            exchange = @Exchange(value = RabbitQueueExchangeConstant.ExchangeName.ALI_CHAT_EXCHANGE),
            key = RabbitQueueExchangeConstant.RoutingKey.ALI_CHAT_ROUTINGKEY),
            ackMode = "AUTO", concurrency = "1-10")
    public void chat(MyMessage<ChatDto> message) throws IOException {
        ChatDto chatVo = message.getData();
        SseEmitter sseEmitter = clients.get(chatVo.getChatMenuId());
        if (sseEmitter == null) {
            return;
        }
        try {
            ChatModel chatModel = getModelByContentType(chatVo.getContentType());
            if (chatModel == null || !StringUtils.hasLength(chatModel.getModel()) || !StringUtils.hasLength(chatModel.getApiKey())) {
                if (!StringUtils.hasLength(chatModel.getApiKey())) {
                    sseEmitter.send(SseEmitter.event().id(chatVo.getChatMenuId()).name("err").data("API KEY 失效!!!"));
                } else if (!StringUtils.hasLength(chatModel.getModel())) {
                    sseEmitter.send(SseEmitter.event().id(chatVo.getChatMenuId()).name("err").data("模型不可用!!!"));
                } else {
                    sseEmitter.send(SseEmitter.event().id(chatVo.getChatMenuId()).name("err").data("系统错误！请稍后再试"));
                }
                sseEmitter.complete();
            } else {
                chatVo.setModel(chatModel.getModel());
                chatVo.setApiKey(chatModel.getApiKey());
                chatVo.setIsCache(chatModel.getIsCache() != null ? chatModel.getIsCache() : 2);
                chatVo.setLimitNum(chatModel.getLimitNum() != null ? chatModel.getLimitNum() : 0);
                if (chatVo.getContentType() == 0) {
                    //通义千问
                    qwenChat(chatVo, sseEmitter, chatVo.getUserId());
                } else if (chatVo.getContentType() == 1) {
                    //通义万象
                    wanxChat(chatVo, sseEmitter, chatVo.getUserId());
                } else if (chatVo.getContentType() == 2) {
                    //创意字生成
                    if (!StringUtils.hasLength(chatVo.getPrompt())) {
                        sseEmitter.send(SseEmitter.event().id(chatVo.getChatMenuId()).name("err").data("请先设置期望创意样式的描述提示词！！！"));
                        sseEmitter.complete();
                    }
                    creativeWord(chatVo, sseEmitter, chatVo.getUserId());
                }
            }
            sseEmitter.onCompletion(() -> {
                clients.remove(chatVo.getChatMenuId());
            });
            sseEmitter.onError((i) -> {
                sseEmitter.complete();
                clients.remove(chatVo.getChatMenuId());
            });
        } catch (Exception e) {
            sseEmitter.onError((i) -> {
                sseEmitter.complete();
                clients.remove(chatVo.getChatMenuId());

            });
        }
    }

    //WordArt锦书-创意文字生成
    private void creativeWord(ChatDto chatVo, SseEmitter sseEmitter, String userId) throws IOException {
        if (verifyNums(userId, chatVo.getLimitNum(), chatVo.getContentType())) {
            sseEmitter.send(SseEmitter.event().id(chatVo.getChatMenuId()).name("err").data("今日图片生成数量已达上限！"));
            sseEmitter.complete();
        } else {
            HttpEntity baseHttpEntity = getBaseHttpEntity(chatVo.getModel(), chatVo.getApiKey(), chatVo.getQuestion(), chatVo.getPrompt());
            CreativeWordNums creativeWordNums = null;
            if (chatVo.getModel().equals(CreativeWordNums.TEXT_TEXTURE.getVale())) {
                creativeWordNums = CreativeWordNums.TEXT_TEXTURE;
            } else if (chatVo.getModel().equals(CreativeWordNums.TEXT_DISTORTION.getVale())) {
                chatVo.setQuestion(chatVo.getQuestion().replaceAll("/n", ""));
                if (chatVo.getQuestion().length() > 200) {
                    sseEmitter.send(SseEmitter.event().id(chatVo.getChatMenuId()).name("err").data("创意文字不能超过200个字！"));
                    sseEmitter.complete();
                    return;
                }
                //中文判断
                if (!chatVo.getQuestion().matches("^[\\u4e00-\\u9fa5]+$")) {
                    sseEmitter.send(SseEmitter.event().id(chatVo.getChatMenuId()).name("err").data("创意文字只能是中文！"));
                    sseEmitter.complete();
                    return;
                }
                creativeWordNums = CreativeWordNums.TEXT_DISTORTION;
            } else {
                sseEmitter.send(SseEmitter.event().id(chatVo.getChatMenuId()).name("err").data("系统错误！请稍后再试"));
                sseEmitter.complete();
                return;
            }
            try {
                ResponseEntity<String> exchange = restTemplate.exchange(creativeWordNums.getUrl(), HttpMethod.POST, baseHttpEntity, String.class);
                //异步任务id
                String taskId = JSONObject.parseObject(JSONObject.parseObject(exchange.getBody()).get("output").toString()).get("task_id").toString();
                String fileUrl = "";
                Boolean isFlage = true;
                while (isFlage) {
                    ResponseEntity<String> getUrl = restTemplate.exchange("https://dashscope.aliyuncs.com/api/v1/tasks/" + taskId, HttpMethod.GET, new HttpEntity<>(baseHttpEntity.getHeaders()), String.class);
                    //获取任务状态
                    String output = JSONObject.parseObject(getUrl.getBody()).get("output").toString();
                    String taskStatus = JSONObject.parseObject(output).get("task_status").toString();
                    switch (taskStatus) {
                        case "SUCCEEDED":
                            JSONArray results = JSONArray.parseArray(JSONObject.parseObject(output).get("results").toString());
                            if (creativeWordNums.getVale().equals(CreativeWordNums.TEXT_TEXTURE.getVale())) {
                                fileUrl = JSONObject.parseObject(results.get(0).toString()).getString("url");
                            } else {
                                fileUrl = JSONObject.parseObject(results.get(0).toString()).getString("png_url");
                            }
                            isFlage = false;
                            break;
                        case "FAILED":
                            throw new ErrorException(11000, "任务异常");
                        case "RUNNING":
                            Thread.sleep(2000);
                            break;
                        case "PENDING":
                            Thread.sleep(2000);
                            break;
                        default:
                            throw new ErrorException(11000, "任务异常");
                    }
                }
                GenerationOutput output = new GenerationOutput();
                output.setText(uploadFile(fileUrl));
                sseEmitter.send(SseEmitter.event().id(chatVo.getChatMenuId()).name("data").data(output));
                //完成
                sseEmitter.complete();
                ThreadUtils.asyncSumbit(() -> {
                    int count = count(new LambdaQueryWrapper<ChatContent>()
                            .eq(ChatContent::getChatMenuId, chatVo.getChatMenuId()));
                    if (count == 0) {
                        updateChatMenu(chatVo);
                    }
                    //新增记录
                    ChatContent chatContent = new ChatContent();
                    chatContent.setChatMenuId(chatVo.getChatMenuId());
                    chatContent.setAskContent(chatVo.getQuestion());
                    chatContent.setUserId(userId);
                    chatContent.setContentType(chatVo.getContentType());
                    chatContent.setReplyContent(output.getText());
                    baseMapper.insert(chatContent);
                });
            } catch (Exception e) {
                e.printStackTrace();
                sseEmitter.send(SseEmitter.event().id(chatVo.getChatMenuId()).name("err").data("系统错误！请稍后再试"));
                sseEmitter.complete();
            }
        }

    }

    @NotNull
    private String uploadFile(String fileUrl) throws IOException {
        URL netWordUrl = new URL(fileUrl);
        HttpURLConnection connection = (HttpURLConnection) netWordUrl.openConnection();
        connection.connect();
        if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
            InputStream inputStream = connection.getInputStream();
            fileUrl = ossUtil.upload("image/", IdWorker.getIdStr().concat(".jpg"), inputStream);
        }
        String url = "![](url)";
        url = url.replace("url", fileUrl);
        return url;
    }

    /**
     * 通义万象
     *
     * @param chatVo
     * @param sseEmitter
     * @param userId
     * @throws IOException
     * @throws NoApiKeyException
     */
    private void wanxChat(ChatDto chatVo, SseEmitter sseEmitter, String userId) throws IOException, NoApiKeyException {
        if (verifyNums(userId, chatVo.getLimitNum(), chatVo.getContentType())) {
            sseEmitter.send(SseEmitter.event().id(chatVo.getChatMenuId()).name("err").data("今日图片生成数量已达上限！"));
            sseEmitter.complete();
        } else {
            ImageSynthesis is = new ImageSynthesis();
            ImageSynthesisParam param = ImageSynthesisParam.builder()
                    .model(ImageSynthesis.Models.WANX_V1)
                    .apiKey(chatVo.getApiKey())
                    .n(1)
                    .size("1280*720")
                    .prompt(chatVo.getQuestion())
                    .build();
            GenerationOutput output = new GenerationOutput();
            ImageSynthesisResult call = is.call(param);
            //上传到本地oss
            String fileUrl = call.getOutput().getResults().get(0).get("url");
            output.setText(uploadFile(fileUrl));
            sseEmitter.send(SseEmitter.event().id(chatVo.getChatMenuId()).name("data").data(output));
            //完成
            sseEmitter.complete();
            ThreadUtils.asyncSumbit(() -> {
                int count = count(new LambdaQueryWrapper<ChatContent>()
                        .eq(ChatContent::getChatMenuId, chatVo.getChatMenuId()));
                if (count == 0) {
                    updateChatMenu(chatVo);
                }
                //新增记录
                ChatContent chatContent = new ChatContent();
                chatContent.setChatMenuId(chatVo.getChatMenuId());
                chatContent.setAskContent(chatVo.getQuestion());
                chatContent.setUserId(userId);
                chatContent.setContentType(1);
                chatContent.setReplyContent(output.getText());
                baseMapper.insert(chatContent);
            });
        }

    }


    // 验证图片生成数量
    private Boolean verifyNums(String userId, Integer limitNum, Integer contentType) {
        LocalDateTime dayStart = LocalDateTimeUtil.getDayStart(LocalDateTime.now());
        LocalDateTime dayEnd = LocalDateTimeUtil.getDayEnd(LocalDateTime.now());
        Integer count = lambdaQuery()
                .eq(ChatContent::getUserId, userId)
                .eq(ChatContent::getContentType, contentType)
                .between(ChatContent::getCreateTime, dayStart, dayEnd)
                .count();
        if (count >= limitNum) {
            return true;
        }
        return false;
    }

    /**
     * 通义千问
     *
     * @param chatVo
     * @param sseEmitter
     * @param userId
     * @throws IOException
     * @throws NoApiKeyException
     * @throws InputRequiredException
     */
    private void qwenChat(ChatDto chatVo, SseEmitter sseEmitter, String userId) throws IOException, NoApiKeyException, InputRequiredException {
        if (verifyTokens(userId, chatVo.getLimitNum())) {
            sseEmitter.send(SseEmitter.event().id(chatVo.getChatMenuId()).name("err").data("今日流量已达上限！"));
            sseEmitter.complete();
        } else {
            //启用缓存时 采用多轮对话模式
            List<Message> messages = new ArrayList<>();
            if (chatVo.getIsCache() == 1) {
                messages = getChatContentCache(chatVo.getChatMenuId());
            }
            messages.add(Message.builder().role(Role.USER.getValue()).content(chatVo.getQuestion()).build());
            Generation gen = new Generation();
            QwenParam param = QwenParam.builder()
                    .model(chatVo.getModel())
                    .apiKey(chatVo.getApiKey())
                    .messages(messages)
                    .enableSearch(true)
                    .topP(0.8)
                    .build();
            Flowable<GenerationResult> result = gen.streamCall(param);
            try {
                result.blockingForEach(message -> {
                    sseEmitter.send(SseEmitter.event().id(chatVo.getChatMenuId()).name("data").data(message.getOutput()));
                    String finishReason = message.getOutput().getFinishReason();
                    if (StringUtils.hasLength(finishReason) && "stop".equals(finishReason)) {
                        //完成
                        sseEmitter.complete();
                        //记录
                        ThreadUtils.asyncSumbit(() -> {
                            int count = count(new LambdaQueryWrapper<ChatContent>()
                                    .eq(ChatContent::getChatMenuId, chatVo.getChatMenuId()));
                            if (count == 0) {
                                updateChatMenu(chatVo);
                            }
                            addChatContent(chatVo, message, userId);
                            if (chatVo.getIsCache() == 1) {
                                addChatContentCache(chatVo, message);
                            }
                        });
                    }
                });
            } catch (Exception e) {
                sseEmitter.send(SseEmitter.event().id(chatVo.getChatMenuId()).name("err").data("系统错误，请稍后再试！"));
                sseEmitter.complete();
                e.printStackTrace();
            }
        }
    }

    private boolean updateChatMenu(ChatDto chatDto) {
        try {
            ChatMenu chatMenu = new ChatMenu();
            chatMenu.setId(chatDto.getChatMenuId());
            chatMenu.setChatMenuName(chatDto.getQuestion().length() > 20 ? chatDto.getQuestion().substring(0, 20) : chatDto.getQuestion());
            return chatMenuService.updateById(chatMenu);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

    /**
     * 校验流量
     *
     * @param userId
     * @param limitNum
     * @return
     */
    private boolean verifyTokens(String userId, Integer limitNum) {
        LocalDateTime dayStart = LocalDateTimeUtil.getDayStart(LocalDateTime.now());
        LocalDateTime dayEnd = LocalDateTimeUtil.getDayEnd(LocalDateTime.now());
        List<ChatContent> list = lambdaQuery()
                .eq(ChatContent::getUserId, userId)
                .eq(ChatContent::getContentType, 0)
                .between(ChatContent::getCreateTime, dayStart, dayEnd)
                .list();
        int sum = list.stream().mapToInt(i -> i.getAskTokens() + i.getReplyTokens()).sum();
        if (sum > limitNum) {
            return true;
        }
        return false;
    }

    //新增缓存聊天内容缓存，已完成多轮对话
    private void addChatContentCache(ChatDto chatVo, GenerationResult message) {
        ListOperations<String, String> listOperations = redisTemplate.opsForList();
        String redisKey = ResdisKeyEnum.CHAT_CONTENT_CACHE.getRedisPath().concat(chatVo.getChatMenuId());
        Integer userTotal = message.getUsage().getInputTokens() + message.getUsage().getOutputTokens();
        Integer totalToken = 0;
        //取出现有缓存内容
        List<String> range = listOperations.range(redisKey, 0, -1);
        if (!range.isEmpty()) {
            for (String s : range) {
                ChatContentCacheVo chatContentCacheVo = JSONObject.parseObject(s, ChatContentCacheVo.class);
                totalToken += chatContentCacheVo.getTotalTokens();
            }
            while (totalToken > qwenAuthConfig.getCacheToken()) {
                if (totalToken == 0) {
                    break;
                }
                ChatContentCacheVo chatContentCacheVo = JSONObject.parseObject(listOperations.leftPop(redisKey), ChatContentCacheVo.class);
                totalToken -= chatContentCacheVo.getTotalTokens();
            }
        }
        ChatContentCacheVo chatContentCache = new ChatContentCacheVo();
        chatContentCache.setChatMenuId(chatVo.getChatMenuId());
        chatContentCache.setAskContent(chatVo.getQuestion());
        chatContentCache.setTotalTokens(userTotal - totalToken);
        chatContentCache.setReplyContent(message.getOutput().getText());
        listOperations.rightPush(ResdisKeyEnum.CHAT_CONTENT_CACHE.getRedisPath().concat(chatVo.getChatMenuId()), JSONObject.toJSONString(chatContentCache));
    }

    //新增缓存聊天内容缓存，已完成多轮对话
    private List<Message> getChatContentCache(String chatMenuId) {
        ListOperations<String, String> listOperations = redisTemplate.opsForList();
        String redisKey = ResdisKeyEnum.CHAT_CONTENT_CACHE.getRedisPath().concat(chatMenuId);
        List<String> range = listOperations.range(redisKey, 0, -1);
        List<Message> messages = new ArrayList<>();
        for (String s : range) {
            ChatContentCacheVo chatContentCacheVo = JSONObject.parseObject(s, ChatContentCacheVo.class);
            if (!StringUtils.hasLength(chatContentCacheVo.getAskContent()) || !StringUtils.hasLength(chatContentCacheVo.getReplyContent())) {
                return new ArrayList<>();
            }
            messages.add(Message.builder().role(Role.USER.getValue()).content(chatContentCacheVo.getAskContent()).build());
            messages.add(Message.builder().role(Role.ASSISTANT.getValue()).content(chatContentCacheVo.getReplyContent()).build());
        }
        return messages;
    }

    /**
     * 新增聊天内容
     *
     * @param chatVo
     * @param message
     * @param userId
     */
    public void addChatContent(ChatDto chatVo, GenerationResult message, String userId) {
        ChatContent chatContent = new ChatContent();
        chatContent.setChatMenuId(chatVo.getChatMenuId());
        chatContent.setAskContent(chatVo.getQuestion());
        chatContent.setUserId(userId);
        chatContent.setAskTokens(message.getUsage().getInputTokens());
        chatContent.setReplyTokens(message.getUsage().getOutputTokens());
        chatContent.setReplyContent(message.getOutput().getText());
        baseMapper.insert(chatContent);
    }

    @Override
    public SseEmitter addSse(String id) {
        if (!StringUtils.hasLength(id)) {
            return null;
        }
        SseEmitterServer sseEmitter = new SseEmitterServer(-1L);
        clients.put(id, sseEmitter);
        try {
            sseEmitter.send(SseEmitter.event().id(id).name("start").data("开始"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return sseEmitter;
    }

    @Override
    public List<ChatContentListVo> getList(String chatMenuId) {
        List<ChatContent> list = lambdaQuery().eq(ChatContent::getChatMenuId, chatMenuId).orderByAsc(ChatContent::getCreateTime).list();
        return BeanDtoVoUtil.listVo(list, ChatContentListVo.class);
    }

    @Override
    public List<ChatTokenStatisticsVo> tokenStatistics(Integer type) {
        String userId = JwtUtil.getJwtUser(request).getUserId();
        SysRole roleNameByUserId = roleService.getRoleNameByUserId(userId);
        if (!userCode.contains(roleNameByUserId.getCode())) {
            userId = null;
        }
        List<ChatTokenStatisticsVo> res = new ArrayList<>();
        if (type == 1) {
            LocalDateTime endTime = LocalDateTime.now();
            LocalDateTime startTime = endTime.minus(6, ChronoUnit.DAYS);
            List<ChatTokenStatisticsVo> vos = baseMapper.tokenStatistics(userId, startTime, endTime, "%Y-%m-%d");
            //近7天
            List<String> dayList = LocalDateTimeUtil.getBetweenDayList(startTime, endTime);
            res = dayList.stream().map(i -> {
                ChatTokenStatisticsVo vo = new ChatTokenStatisticsVo();
                vo.setTime(i);
                vo.setTokens(0);
                for (ChatTokenStatisticsVo chatTokenStatisticsVo : vos) {
                    if (chatTokenStatisticsVo.getTime().equals(i)) {
                        vo.setTokens(chatTokenStatisticsVo.getTokens());
                    }
                }
                return vo;
            }).collect(Collectors.toList());
        } else if (type == 2) {
            LocalDateTime endTime = LocalDateTimeUtil.yearLastDay(LocalDateTime.now(), 0);
            LocalDateTime startTime = LocalDateTimeUtil.yearFirstDay(LocalDateTime.now(), 0);
            List<ChatTokenStatisticsVo> vos = baseMapper.tokenStatistics(userId, startTime, endTime, "%Y-%m");
            //近7天
            List<String> dayList = LocalDateTimeUtil.getBetweenMonthsList(startTime, endTime);
            res = dayList.stream().map(i -> {
                ChatTokenStatisticsVo vo = new ChatTokenStatisticsVo();
                vo.setTime(i);
                vo.setTokens(0);
                for (ChatTokenStatisticsVo chatTokenStatisticsVo : vos) {
                    if (chatTokenStatisticsVo.getTime().equals(i)) {
                        vo.setTokens(chatTokenStatisticsVo.getTokens());
                    }
                }
                return vo;
            }).collect(Collectors.toList());
        }
        return res;
    }

    @Override
    public ChatTokenStatisticsAllVo tokenStatisticsAll() {
        ChatTokenStatisticsAllVo vo = new ChatTokenStatisticsAllVo();
        String userId = JwtUtil.getJwtUser(request).getUserId();
        List<ChatTokenStatisticsAllVo> vos = baseMapper.ChatTokenStatisticsAllVo(userId);
        vos.forEach(v -> {
            vo.setTokens(vo.getTokens() + v.getTokens());
            vo.setCreativeNum(v.getCreativeNum() + vo.getCreativeNum());
            vo.setPaintNum(v.getPaintNum() + vo.getPaintNum());
        });
        return vo;
    }


    public ChatModel getModelByContentType(Integer contentType) {
        ChatModel chatModel = chatModelService.getModelByContentType(contentType);
        return chatModel;
    }


    public HttpEntity getBaseHttpEntity(String model, String apiKey, String question, String prompt) {
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", "Bearer " + apiKey);
        headers.set("Content-Type", "application/json");
        headers.set("X-DashScope-Async", "enable");
        Map<String, Object> map = new HashMap<>();
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("n", 1);
        Map<String, Object> input = new HashMap<>();
        input.put("prompt", prompt);
        if (model.equals(CreativeWordNums.TEXT_TEXTURE.getVale())) {
            Map<String, Object> text = new HashMap<>();
            text.put("text_content", question);
            text.put("font_name", "dongfangdakai");
            text.put("output_image_ratio", "16:9");
            parameters.put("image_short_size", 1024);
            input.put("text", text);
            input.put("texture_style", "scene");
        } else if (model.equals(CreativeWordNums.TEXT_DISTORTION.getVale())) {
            input.put("text", question);
        }
        map.put("model", model);
        map.put("input", input);
        map.put("parameters", parameters);
        return new HttpEntity<>(map, headers);
    }
}
